//vm : vm实例对象
//exp:指令对应的表达式
//cb:持有更新器的回调
function Watcher(vm, exp, cb) {
    // this : watcher的实例对象
    this.cb = cb;
    this.vm = vm;
    //obj.msg.text
    this.exp = exp;
    //每一个watcher都要一个depIds的属性 它是一个对象!!
    this.depIds = {};
    //value : exp在data中对应的值
    this.value = this.get();
}

Watcher.prototype = {
    update: function() {
        this.run();
    },
    run: function() {
        //"hello Kitty"
        var value = this.get();
        //"hello world"
        var oldVal = this.value;
        if (value !== oldVal) {
            this.value = value;
            //如果发现新设置的值 和 老值不一样
            this.cb.call(this.vm, value, oldVal);
        }
    },
    addDep: function(dep) {
        //this:对应的watcher
        if (!this.depIds.hasOwnProperty(dep.id)) {
            //构建了dep和watcher的1对多关系!
            dep.addSub(this);
            //构建了watcher和dep的1对多关系!
            this.depIds[dep.id] = dep;
        }
    },
    get: function() {
        Dep.target = this; //开启了Dep.target;Dep.target就是一个watcher
        var value = this.getVMVal(); //数据劫持时的get方法一直在被调用!!
        Dep.target = null;//关闭了Dep.target
        return value;
    },


    //根据exp去data中找exp对应的值!
    //exp中的任意一层属性都是要被访问到的
    getVMVal: function() {
        var exp = this.exp.split('.');
        var val = this.vm._data;
        exp.forEach(function(k) {
            //对应k的get方法要被调用
            val = val[k];
        });
        return val;
    }
};